#pragma once
#include<iostream>
#include<jsoncpp/json/json.h>

class Request
{
public:
    Request():_x(0),_y(0),_oper(0)
    {}
    ~Request(){}
    //序列化与反序列化
    bool Serialize(std::string* out)//输出型参数，序列化后的结果由参数带出
    {
        //使用Json
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        //将json 串转换为字符串
        Json::StyledWriter writer;
        *out = writer.write(root);
        if(out->empty()) return false;
        return true;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        //将字符串解析为Json串
        bool ret = reader.parse(in , root);
        if(ret==false) return false;

        //将Json串中的数据放入结构中
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }
    //Get函数
    int X()
    {
        return _x;
    }
    int Y()
    {
        return _y;
    }
    char Oper()
    {
        return _oper;
    }

// private:
    //定制协议
    int _x;
    int _y;
    char _oper;
};

class Responce
{
public:
    Responce():_result(0) , _code(0)
    {}
    ~Responce(){}

    //序列化与反序列化
    bool Serialize(std::string* out)//输出型参数，序列化后的结果由参数带出
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::StyledWriter writer;
        *out = writer.write(root);
        if(out->empty()) return false;
        return true;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ret = reader.parse(in , root);
        if(!ret) return false;

        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return true;
    }
    //提供一些set 方法
   void SetResult(int r)
   {
        _result = r;
   }
   void SetCode(int c)
   {
        _code = c;
   }
   void  Print()
   {
        std::cout << _result <<"[" << _code << "]" <<std::endl; 
   }
private:
    int _result;
    int _code;//标识计算结果是否可信
};

static const std::string sep = "\r\n";

//添加json 字符串的长度来确认读取是否完整
class Protocol
{
public:
    Protocol(){}
    ~Protocol(){}
    //在json 串前添加json 字符串的长度、\r\n
    static std::string Package(std::string &jsonstr)
    {
        //先对jsonstr 进行判空处理
        if(jsonstr.empty()) return std::string();

        std::string json_length = std::to_string(jsonstr.size());
        return json_length + sep + jsonstr + sep;
    }

    //检查
    static bool DigitSafeCheck(const std::string str)
    {
        for(int i = 0;i<str.size();i++)
        {
            if(!(str[i] >='0' && str[i]<='9')) return false;
        }
        return true;
    }

    //判断从接受缓冲区获取的json 串是否完整；如果有完整的json 串，获取并返回
    //origin_str 为输入、输出型参数 package 为输出型参数
    //返回0 表示origin_str 中没有完整的报文，需要重新获取； -1：报文协议错误 ； >0 获取的报文总长度
    static int Unpack(std::string& origin_str , std::string* package)
    {
        // if(origin_str.empty()) return 0;
        if(!package) return 0;

        //从origin_str 中找到第一个分隔符，拿到json 串的长度信息
        auto pos = origin_str.find(sep);
        if(pos == std::string::npos) return 0;//没有分隔符的话，这条报文一定不完整

        std::string len_str = origin_str.substr(0 , pos);
        //检查len_str 中是否有非数字字符
        if(!DigitSafeCheck(len_str))
        {
            return -1;
        }
        //判断整个报文长度是否完整
        int digit_len = std::stoi(len_str);
        int target_len = len_str.size() + sep.size()*2+digit_len;
        if(origin_str.size() < target_len) return 0;

        //走到此处，就能保证origin_str 中至少有一个完整的报文
        *package = origin_str.substr(pos + sep.size() , digit_len);
        //origin_str 为输入、输出型参数
        origin_str.erase(0,target_len);
        return package->size();
    }
};